package org.hfy.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.hfy.dto.warehouse.InboundCreateDTO;
import org.hfy.dto.warehouse.InboundQueryDTO;
import org.hfy.dto.warehouse.OutsourcingInboundCreateDTO;
import org.hfy.entity.Inbound;
import org.hfy.entity.Inventory;
import org.hfy.entity.Outsourcing;
import org.hfy.entity.Quotation;
import org.hfy.entity.QuotationItem;
import org.hfy.mapper.InboundMapper;
import org.hfy.mapper.OutsourcingMapper;
import org.hfy.mapper.QuotationItemMapper;
import org.hfy.mapper.QuotationMapper;
import org.hfy.service.InboundService;
import org.hfy.service.InventoryService;
import org.hfy.utils.FactoryNoGenerator;
import org.hfy.exception.WarehouseException;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

/**
 * 入库管理服务实现类
 * 
 * @author hfy
 * @version 1.0
 */
@Service
public class InboundServiceImpl extends ServiceImpl<InboundMapper, Inbound> implements InboundService {

    @Autowired
    private FactoryNoGenerator factoryNoGenerator;

    @Autowired
    private InventoryService inventoryService;

    @Autowired
    private QuotationItemMapper quotationItemMapper;

    @Autowired
    private OutsourcingMapper outsourcingMapper;

    @Autowired
    private QuotationMapper quotationMapper;

    @Override
    public IPage<QuotationItem> getAvailableOrdersPage(InboundQueryDTO queryDTO) {
        Page<QuotationItem> page = new Page<>(queryDTO.getCurrent(), queryDTO.getSize());
        return baseMapper.selectAvailableOrdersPage(page, queryDTO);
    }

    @Override
    public IPage<Inbound> getInboundRecordsPage(InboundQueryDTO queryDTO) {
        Page<Inbound> page = new Page<>(queryDTO.getCurrent(), queryDTO.getSize());
        return baseMapper.selectInboundRecordsPage(page, queryDTO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Inbound createInbound(InboundCreateDTO createDTO) {
        // 获取报价明细信息
        QuotationItem quotationItem = quotationItemMapper.selectById(createDTO.getQuotationItemId());
        if (quotationItem == null) {
            throw new WarehouseException.DataNotFoundException("报价明细", createDTO.getQuotationItemId());
        }

        // 创建入库单
        Inbound inbound = new Inbound();
        BeanUtils.copyProperties(createDTO, inbound);
        
        // 生成入库单号和厂内编号
        inbound.setInboundNo(generateInboundNo());
        inbound.setFactoryNo(generateFactoryNo());
        
        // 从报价明细复制技术参数
        copyTechnicalParams(inbound, quotationItem);
        
        // 设置状态
        inbound.setStatus("已入库");
        inbound.setCreatedBy("system");
        
        // 保存入库单
        save(inbound);
        
        // 更新或创建库存记录
        updateInventory(inbound);
        
        return inbound;
    }

    @Override
    public String generateFactoryNo() {
        return factoryNoGenerator.generateFactoryNo();
    }

    @Override
    public Integer getTotalInboundQuantityByQuotationItemId(Long quotationItemId) {
        List<Inbound> inbounds = baseMapper.selectByQuotationItemId(quotationItemId);
        return inbounds.stream()
                .mapToInt(Inbound::getInboundQuantity)
                .sum();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Inbound createOutsourcingInbound(OutsourcingInboundCreateDTO createDTO) {
        // 获取外发单信息
        Outsourcing outsourcing = outsourcingMapper.selectById(createDTO.getOutsourcingId());
        if (outsourcing == null) {
            throw new WarehouseException.DataNotFoundException("外发单", createDTO.getOutsourcingId());
        }

        // 验证入库数量不能超过剩余可入库数量
        Integer totalInboundQuantity = getTotalInboundQuantityByOutsourcingId(createDTO.getOutsourcingId());
        int remainingQuantity = outsourcing.getQuantity() - totalInboundQuantity;
        if (createDTO.getInboundQuantity() > remainingQuantity) {
            throw new WarehouseException.QuantityValidationException(
                String.format("入库数量(%d)超过剩余可入库数量(%d)", createDTO.getInboundQuantity(), remainingQuantity));
        }

        // 获取报价单信息获取客户信息
        Quotation quotation = quotationMapper.selectById(outsourcing.getQuotationId());
        if (quotation == null) {
            throw new WarehouseException.DataNotFoundException("报价单", outsourcing.getQuotationId());
        }

        // 创建入库单
        Inbound inbound = new Inbound();
        BeanUtils.copyProperties(createDTO, inbound);
        
        // 生成入库单号
        inbound.setInboundNo(generateInboundNo());
        
        // 从外发单和报价单复制相关信息
        inbound.setQuotationId(outsourcing.getQuotationId());
        inbound.setQuotationItemId(outsourcing.getQuotationItemId());
        inbound.setCustomerCode(quotation.getCustomerCode());
        inbound.setCustomerName(quotation.getCustomerName());
        inbound.setOrderQuantity(outsourcing.getQuantity());
        
        // 计算总入库数量（入库数量+备品数量）
        int totalQuantity = createDTO.getInboundQuantity() + (createDTO.getSpareQuantity() != null ? createDTO.getSpareQuantity() : 0);
        inbound.setSpareQuantity(createDTO.getSpareQuantity());
        
        // 设置状态
        inbound.setStatus("已入库");
        inbound.setCreatedBy("system");
        
        // 保存入库单
        save(inbound);
        
        // 更新或创建库存记录
        updateInventory(inbound);
        
        return inbound;
    }

    @Override
    public Integer getTotalInboundQuantityByOutsourcingId(Long outsourcingId) {
        List<Inbound> inbounds = lambdaQuery()
                .eq(Inbound::getOutsourcingId, outsourcingId)
                .list();
        return inbounds.stream()
                .mapToInt(Inbound::getInboundQuantity)
                .sum();
    }

    /**
     * 生成入库单号
     * 格式：RK + yyyyMMddHHmmss + 3位序号
     */
    private String generateInboundNo() {
        try {
            String dateTimeStr = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
            return "RK" + dateTimeStr + String.format("%03d", System.currentTimeMillis() % 1000);
        } catch (Exception e) {
            throw new WarehouseException.NumberGenerationException("入库单号", e);
        }
    }

    /**
     * 从报价明细复制技术参数到入库单
     */
    private void copyTechnicalParams(Inbound inbound, QuotationItem quotationItem) {
        inbound.setLayers(quotationItem.getLayers());
        inbound.setThickness(quotationItem.getThickness());
        inbound.setSurfaceTreatment(quotationItem.getSurfaceTreatment());
        inbound.setSolderMask(quotationItem.getSolderMask());
        inbound.setCharacter(quotationItem.getCharacter());
        inbound.setBoardMaterial(quotationItem.getBoardMaterial());
        inbound.setDeliverySize(quotationItem.getDeliverySize());
        inbound.setPanelization(quotationItem.getPanelization());
        inbound.setInnerCopper(quotationItem.getInnerCopper());
        inbound.setOuterCopper(quotationItem.getOuterCopper());
        inbound.setViaProcess(quotationItem.getViaProcess());
        inbound.setTesting(quotationItem.getTesting());
        inbound.setTestingFee(quotationItem.getTestingFee());
        inbound.setIsUrgent(quotationItem.getIsUrgent());
        inbound.setUnitPrice(quotationItem.getUnitPrice());
        inbound.setSampleFee(quotationItem.getSampleFee());
        inbound.setTotalAmount(quotationItem.getTotalAmount());
        inbound.setIsTaxIncluded(quotationItem.getIsTaxIncluded());
        inbound.setOrderDate(quotationItem.getCreatedAt().toLocalDate());
        inbound.setDeliveryDate(quotationItem.getDeliveryDate());
        inbound.setPurchaseOrderNo(quotationItem.getPurchaseOrderNo());
    }

    /**
     * 更新或创建库存记录
     */
    private void updateInventory(Inbound inbound) {
        // 根据厂内编号查询库存
        Inventory inventory = inventoryService.getByFactoryNo(inbound.getFactoryNo());
        
        if (inventory == null) {
            // 创建新的库存记录
            inventory = new Inventory();
            inventory.setFactoryNo(inbound.getFactoryNo());
            inventory.setQuotationId(inbound.getQuotationId());
            inventory.setQuotationItemId(inbound.getQuotationItemId());
            inventory.setCustomerCode(inbound.getCustomerCode());
            inventory.setCustomerName(inbound.getCustomerName());
            inventory.setProductName(inbound.getProductName());
            inventory.setMaterialCode(inbound.getMaterialCode());
            
            // 复制技术参数
            copyTechnicalParamsToInventory(inventory, inbound);
            
            inventory.setTotalInboundQuantity(inbound.getInboundQuantity());
            inventory.setTotalOutboundQuantity(0);
            inventory.setCurrentStockQuantity(inbound.getInboundQuantity());
            inventory.setSpareQuantity(inbound.getSpareQuantity());
            inventory.setUnitPrice(inbound.getUnitPrice());
            inventory.setTotalAmount(inbound.getTotalAmount());
            inventory.setLastInboundDate(inbound.getInboundDate());
            inventory.setStatus("有库存");
            inventory.setSalesperson(inbound.getSalesperson());
            
            inventoryService.save(inventory);
        } else {
            // 使用统一的库存更新方法
            inventoryService.updateStockQuantity(inbound.getFactoryNo(), inbound.getInboundQuantity(), null);
        }
    }

    /**
     * 复制技术参数到库存记录
     */
    private void copyTechnicalParamsToInventory(Inventory inventory, Inbound inbound) {
        inventory.setLayers(inbound.getLayers());
        inventory.setThickness(inbound.getThickness());
        inventory.setSurfaceTreatment(inbound.getSurfaceTreatment());
        inventory.setSolderMask(inbound.getSolderMask());
        inventory.setCharacter(inbound.getCharacter());
        inventory.setBoardMaterial(inbound.getBoardMaterial());
        inventory.setDeliverySize(inbound.getDeliverySize());
    }
} 